package com.pokermind.model.exception;

import com.pokermind.model.enums.ErrorCode;

/**
 * 扑克业务异常类
 * 严格按照API文档6.2节业务错误码体系实现
 * 
 * @author PokerMind Team
 */
public class PokerBusinessException extends RuntimeException {
    
    private final ErrorCode errorCode;
    private final String details;
    
    public PokerBusinessException(ErrorCode errorCode) {
        super(errorCode.getMessage());
        this.errorCode = errorCode;
        this.details = null;
    }
    
    public PokerBusinessException(ErrorCode errorCode, String details) {
        super(errorCode.getMessage());
        this.errorCode = errorCode;
        this.details = details;
    }
    
    public PokerBusinessException(ErrorCode errorCode, String details, Throwable cause) {
        super(errorCode.getMessage(), cause);
        this.errorCode = errorCode;
        this.details = details;
    }
    
    public ErrorCode getErrorCode() {
        return errorCode;
    }
    
    public String getDetails() {
        return details;
    }
    
    // 手牌管理错误
    public static class HandNotFoundException extends PokerBusinessException {
        public HandNotFoundException(Long handId) {
            super(ErrorCode.HAND_NOT_FOUND, "field: hand_record_id, value: " + handId + ", constraint: must_exist_in_database");
        }
    }
    
    public static class HandAlreadyExistsException extends PokerBusinessException {
        public HandAlreadyExistsException(String handId) {
            super(ErrorCode.HAND_ALREADY_EXISTS, "field: hand_id, value: " + handId + ", constraint: must_be_unique");
        }
    }
    
    public static class HandAlreadyCompletedException extends PokerBusinessException {
        public HandAlreadyCompletedException(Long handId) {
            super(ErrorCode.HAND_ALREADY_COMPLETED, "field: hand_record_id, value: " + handId + ", constraint: must_be_active");
        }
    }
    
    public static class HandInvalidStateException extends PokerBusinessException {
        public HandInvalidStateException(String currentState, String requiredState) {
            super(ErrorCode.HAND_INVALID_STATE, "current_state: " + currentState + ", required_state: " + requiredState);
        }
    }
    
    public static class InvalidStreetTransitionException extends PokerBusinessException {
        public InvalidStreetTransitionException(String fromStreet, String toStreet) {
            super(ErrorCode.HAND_INVALID_STREET_TRANSITION, "from: " + fromStreet + ", to: " + toStreet);
        }
    }
    
    public static class BoardCardsMismatchException extends PokerBusinessException {
        public BoardCardsMismatchException(String street, int expected, int actual) {
            super(ErrorCode.HAND_BOARD_CARDS_MISMATCH, 
                  "street: " + street + ", expected: " + expected + ", actual: " + actual);
        }
    }
    
    // 玩家和座位错误
    public static class PlayerSeatOccupiedException extends PokerBusinessException {
        public PlayerSeatOccupiedException(Integer seatNumber) {
            super(ErrorCode.PLAYER_SEAT_OCCUPIED, "seat_number: " + seatNumber);
        }
    }
    
    public static class PlayerNotFoundException extends PokerBusinessException {
        public PlayerNotFoundException(String playerName, Integer seatNumber) {
            super(ErrorCode.PLAYER_NOT_FOUND, "player_name: " + playerName + ", seat_number: " + seatNumber);
        }
    }
    
    public static class MultipleHeroException extends PokerBusinessException {
        public MultipleHeroException() {
            super(ErrorCode.PLAYER_MULTIPLE_HERO, "only_one_hero_allowed");
        }
    }
    
    public static class InsufficientPlayersException extends PokerBusinessException {
        public InsufficientPlayersException(int playerCount) {
            super(ErrorCode.PLAYER_INSUFFICIENT_PLAYERS, 
                  "player_count: " + playerCount + ", minimum_required: 2");
        }
    }
    
    public static class InvalidStackException extends PokerBusinessException {
        public InvalidStackException(String playerName, String stackValue) {
            super(ErrorCode.PLAYER_INVALID_STACK, "player: " + playerName + ", stack: " + stackValue);
        }
    }
    
    // 行动验证错误
    public static class InvalidSeatException extends PokerBusinessException {
        public InvalidSeatException(Integer seatNumber) {
            super(ErrorCode.ACTION_INVALID_SEAT, "seat_number: " + seatNumber);
        }
    }
    
    public static class WrongTurnException extends PokerBusinessException {
        public WrongTurnException(Integer expectedSeat, Integer actualSeat) {
            super(ErrorCode.ACTION_WRONG_TURN, "expected_seat: " + expectedSeat + ", actual_seat: " + actualSeat);
        }
    }
    
    public static class InvalidAmountException extends PokerBusinessException {
        public InvalidAmountException(String actionType, String amount, String constraint) {
            super(ErrorCode.ACTION_INVALID_AMOUNT, 
                  "action: " + actionType + ", amount: " + amount + ", constraint: " + constraint);
        }
    }
    
    public static class InsufficientStackException extends PokerBusinessException {
        public InsufficientStackException(String playerName, String required, String available) {
            super(ErrorCode.ACTION_INSUFFICIENT_STACK, 
                  "player: " + playerName + ", required: " + required + ", available: " + available);
        }
    }
    
    public static class InvalidActionTypeException extends PokerBusinessException {
        public InvalidActionTypeException(String actionType, String allowedActions) {
            super(ErrorCode.ACTION_INVALID_TYPE, "action: " + actionType + ", allowed: " + allowedActions);
        }
    }
    
    public static class MinRaiseViolationException extends PokerBusinessException {
        public MinRaiseViolationException(String amount, String minRaise) {
            super(ErrorCode.ACTION_MIN_RAISE_VIOLATION, "amount: " + amount + ", min_raise: " + minRaise);
        }
    }
    
    public static class PlayerNotActiveException extends PokerBusinessException {
        public PlayerNotActiveException(String playerName) {
            super(ErrorCode.ACTION_PLAYER_NOT_ACTIVE, "player: " + playerName);
        }
    }
    
    // AI服务错误
    public static class AIServiceUnavailableException extends PokerBusinessException {
        public AIServiceUnavailableException(String reason) {
            super(ErrorCode.AI_SERVICE_UNAVAILABLE, reason);
        }
    }
    
    public static class AIAnalysisTimeoutException extends PokerBusinessException {
        public AIAnalysisTimeoutException(int timeoutMs) {
            super(ErrorCode.AI_ANALYSIS_TIMEOUT, "timeout_ms: " + timeoutMs);
        }
    }
    
    public static class AIInsufficientDataException extends PokerBusinessException {
        public AIInsufficientDataException(String missingData) {
            super(ErrorCode.AI_INSUFFICIENT_DATA, "missing: " + missingData);
        }
    }
    
    public static class AIInvalidParametersException extends PokerBusinessException {
        public AIInvalidParametersException(String parameter, String value) {
            super(ErrorCode.AI_INVALID_PARAMETERS, "parameter: " + parameter + ", value: " + value);
        }
    }
    
    public static class AIQuotaExceededException extends PokerBusinessException {
        public AIQuotaExceededException(String quotaType, String limit) {
            super(ErrorCode.AI_QUOTA_EXCEEDED, "quota_type: " + quotaType + ", limit: " + limit);
        }
    }
    
    // 认证和权限错误
    public static class TokenInvalidException extends PokerBusinessException {
        public TokenInvalidException() {
            super(ErrorCode.AUTH_TOKEN_INVALID);
        }
    }
    
    public static class TokenExpiredException extends PokerBusinessException {
        public TokenExpiredException() {
            super(ErrorCode.AUTH_TOKEN_EXPIRED);
        }
    }
    
    public static class InsufficientScopeException extends PokerBusinessException {
        public InsufficientScopeException(String requiredScope) {
            super(ErrorCode.AUTH_INSUFFICIENT_SCOPE, "required_scope: " + requiredScope);
        }
    }
    
    public static class RateLimitedException extends PokerBusinessException {
        public RateLimitedException(String retryAfter) {
            super(ErrorCode.AUTH_RATE_LIMITED, "retry_after: " + retryAfter);
        }
    }
    
    // 用户错误
    public static class UserNotFoundException extends PokerBusinessException {
        public UserNotFoundException(Long userId) {
            super(ErrorCode.USER_NOT_FOUND, "user_id: " + userId);
        }
    }
    
    public static class UserAlreadyExistsException extends PokerBusinessException {
        public UserAlreadyExistsException(String username) {
            super(ErrorCode.USER_ALREADY_EXISTS, "username: " + username);
        }
    }
}